package usersManagement.controller;

import org.hibernate.validator.constraints.NotEmpty;
import org.primefaces.context.RequestContext;
import org.slf4j.Logger;
import usersManagement.model.User;
import usersManagement.service.DuplicateUsernameException;
import usersManagement.service.UserService;
import usersManagement.util.AppLog;

import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Produces;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Named("users")
@SessionScoped
public class UsersController implements Serializable {
// ------------------------------ FIELDS ------------------------------

    private static final long serialVersionUID = 7732326343388447114L;
    
    List<User> usersList ;

    @Inject @AppLog private Logger log; // all implementations are serializable, the interface is not, so the warning can be ignored

    @Inject
    private FacesContext facesContext;

    // subject is not serializable se it cannot injected into a passivating bean
    // it can be made transitional if necessary, but maybe it's better to just look it up if necessary
    //@Inject
    //private Subject loggedUser ;

    @Inject
    private Event<User> userEventSrc;

    @Inject
    private UserService userService ;

    private User selectedUser ;

    @NotEmpty
    private Set<String> selectedUserRoles ;

// --------------------------- INITIALIZATION ---------------------------

    @PostConstruct
    public void init() {
        usersList = userService.findAll() ;
    }

// -------------------------- OTHER METHODS --------------------------

    public void newUser() {
        log.info("Creating new user ");
        selectedUser = new User() ;
        selectedUser.setPassword("12345678");
    }

    public void editUser() {
        log.info("Editing user {}", selectedUser.getUsername());
        selectedUserRoles = new HashSet<String>() ;
        selectedUserRoles.addAll(selectedUser.getRoles()) ;
    }

    public void onUsersListChanged(@Observes final User user) {
        log.info("Refreshing users list");
        usersList = userService.findAll() ;
    }

    public void saveUser() {
        log.info("Saving user {}", selectedUser.getUsername());
        selectedUser.setRoles(selectedUserRoles);
        try {
            userService.save(selectedUser);
            userEventSrc.fire(selectedUser);
        }
        catch (DuplicateUsernameException e) {
            facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), null));
            RequestContext.getCurrentInstance().addCallbackParam("validationFailed", true);
        }
    }

// --------------------- GETTER / SETTER METHODS ---------------------

    @Produces
    @Named
    public User getSelectedUser() {
        return selectedUser;
    }

    public void setSelectedUser(User selectedUser) {
        this.selectedUser = selectedUser;
    }

    public Set<String> getSelectedUserRoles() {
        return selectedUserRoles;
    }

    public void setSelectedUserRoles(Set<String> selectedUserRoles) {
        this.selectedUserRoles = selectedUserRoles;
    }

    @Produces
    @Named
    public List<User> getUsersList() {
        return usersList;
    }

    public void setUsersList(List<User> usersList) {
        this.usersList = usersList;
    }
}
